﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ACLP2P;
using System.ServiceModel;

using System.IO;
using ACLP2P;
using AutonomicComputingLibrary.P2P;
using Agent2.ACLP2PAgent.P2P;
using Agent2.ACLP2PAgent.Agent;

namespace LMU.FinalProject.ACL.P2P
{



    class AgentClient :IAgentPoolCallback ,IDisposable 

    {
        static AgentPoolClient proxy;
        static InstanceContext context;
        public static Agent agent;

        public AgentClient(string AgentName)
        {

            Load(AgentName);
         }

        public static List<Agent> OtherAgents = new List<Agent>();
        bool complete;

        public void   CallBackFunction(string str)
        {
            Console.WriteLine(str);

            if (str.Contains("complete"))
                complete = true;

        }

        public void TalkToOtherAgent()
        {
            foreach (var item in proxy.GetAgents())
            {
                UpdateAgentListAdd(item);
            }

            try
            {
                proxy.Whisper(new Message { sender = agent, recipeint = OtherAgents[1], body = "hello", subject = "hi" });
            }
            catch (Exception)
            {
                
                

            }
            

        }

       public void UpdateAgentListAdd(Agent agent)
       {
           if (AgentClient.agent.Id != agent.Id)
           OtherAgents.Add(agent);
       }

       public void UpdateAgentListRemove(Agent agent)
       {
           OtherAgents.Remove(OtherAgents.Find(b => b.Id == agent.Id));
       }


        public void Load(string name)
        {
            string[] skills = { "p2p" };
           context = new InstanceContext(this);
           proxy = new AgentPoolClient(context, "duplexendpoint1");
           agent = new Agent { Id = Guid.NewGuid().ToString(), Comments = "Good Morning", Name = name, TimeSubmited = DateTime.Now, Skills = skills };
      
           proxy.Subscribe(agent);
      
           Console.WriteLine("Agent Connect to ACL Network");

        //   Help(skills);

           

        }

        private static void Help()
        {
            //ask for help
            AgentTracker at = new AgentTracker();

            string[] args = { "1.txt", @"C:\Users\Jamie\Google Drive\601project\Agent2\Agent2\am122211.txt" };
            at.agent = AgentClient.agent;
            at.args = args;
            at.method = "DownloadFile";
            at.skillthatneedsHelp = AgentClient.agent.Skills[0];
            at.ServiceUri = proxy.Endpoint.ListenUri.AbsoluteUri.ToString();
            Console.WriteLine(proxy.CanIGetSomeHelp(at));
        }




        public void UnLoad()
        {
            context = new InstanceContext(this);
            proxy = new AgentPoolClient(context);
           
            proxy.UnSubscribe(agent);

        } 

        public void Dispose()
        {
            proxy.Close();
        }

        public void CallBackFUnction(string msg)
        {
            Console.WriteLine(msg);
        }


       public bool helpRequired = false;

        public void DownloadFile(string FileToDownload, string downloadto, string SaveAs, int start)
        {
            //get a file
            PeerToPeerClient
                    clientDownload = new PeerToPeerClient();
            DownloadRequest requestData = new DownloadRequest();

            RemoteFileInfo fileInfo = new RemoteFileInfo();
            string [] args = {FileToDownload, downloadto, SaveAs};

  


            int end = 10;

            if (helpRequired)
            {
                end = 5;
                AgentTracker at = new AgentTracker { agent = agent, args = args, method = "DownloadFile", ServiceUri = clientDownload.Endpoint.ListenUri.ToString(), skillthatneedsHelp = "p2p", timeadded = DateTime.Now };

                proxy.CanIGetSomeHelp(at);

            }
            
            string file = ""; 

            for (int x = start; x < end; x++)
            {
              file = FileToDownload +   x.ToString() + ".sg";
                
                Stream source;



                clientDownload.GetFile(ref file , out source);

                using (Stream fileToSave = File.OpenWrite(downloadto +  file))
                {
                    CopyStream(source, fileToSave);
                }
            }
            string lastfile = FileToDownload + "9.sg";

            string[] FILES = Directory.GetFiles(downloadto);

            File.Delete(Path.Combine(new FileInfo(file).Directory.FullName, FileToDownload));

            System.Threading.Thread.Sleep(5000);

                FileIOOPtimization fo = new FileIOOPtimization();

                fo.Merge(SaveAs, downloadto, FileToDownload);
            

        }

        public void UploadFile(string FileToUpload)
        {
            PeerToPeerClient
                    client= new PeerToPeerClient();
            //save a file
            FileInfo fi = new FileInfo(FileToUpload);
            Stream s = new FileStream(fi.FullName, FileMode.Open);

            client.PutFile(fi.Name, fi.Length, s);

            Console.WriteLine(string.Format("{0} file uploaded to server", FileToUpload));


        }

        public List<DownloadRequest> ServerFiles()
        {
             PeerToPeerClient
                    client= new PeerToPeerClient();

             return client.RequestFileInfos().ToList();
        }


        /// <summary>
        /// Copies the contents of input to output. Doesn't close either stream.
        /// </summary>
        public static void CopyStream(Stream input, Stream output)
        {
            byte[] buffer = new byte[8 * 1024];
            int len;
            while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, len);
            }
        }






      
    }
}
